import cv2
import numpy as np
import pyautogui
from datetime import datetime
import time
import keyboard
import winsound  # 导入winsound模块用于播放提示音

from key_presser import SimpleNumberKeysSimulator


class PatternDetector:
    def __init__(self, template_red, template_blue, template_yellow):
        """
        初始化函数，用于设置各个颜色图案的模板。

        :param template_red: 红色图案模板图像
        :param template_blue: 蓝色图案模板图像
        :param template_yellow: 黄色图案模板图像
        """
        self.template_red = template_red
        self.template_blue = template_blue
        self.template_yellow = template_yellow
        self.red_detected_in_image = False  # 新增属性，记录红色图案在当前图像是否已被识别
        self.blue_detected_in_image = False  # 新增属性，记录蓝色图案在当前图像是否已被识别
        self.yellow_detected_in_image = False  # 新增属性，记录黄色图案在当前图像是否已被识别
        self.red_key_pressed = False  # 新增属性，记录红色图案在当前匹配过程中是否已按下按键
        self.blue_key_pressed = False  # 新增属性，记录蓝色图案在当前匹配过程中是否已按下按键
        self.yellow_key_pressed = False  # 新增属性，记录黄色图案在当前匹配过程中是否已按下按键
        self.method = cv2.TM_CCOEFF_NORMED  # 定义匹配方法
        self.threshold = 0.9  # 将颜色阈值修改为0.9，使匹配更严格
        self.first_detection_done = False  # 新增属性，用于标记是否已经完成了首次检测（任意颜色图案）
        self.is_running = False  # 新增属性，用于记录当前程序的运行状态，初始为False表示暂停循环
        self.presser = SimpleNumberKeysSimulator()

    def detect_patterns(self):
        """
        一次性对红、蓝、黄三个颜色图案进行模板匹配的方法，先截取屏幕图像，再使用截取后的图像进行匹配，并处理首次检测到图案的相关逻辑。

        :return: 包含三个图案各自匹配到的图案位置信息以及对应按键值的字典，键为颜色名称，值为包含位置信息列表和按键值的字典
        """
        # 获取屏幕截图作为待检测图像
        screen_image = pyautogui.screenshot()
        screen_image = cv2.cvtColor(np.array(screen_image), cv2.COLOR_RGB2BGR)

        # 获取屏幕截图的尺寸信息，用于计算截取区域
        height, width = screen_image.shape[:2]
        start_x = int(width * 0.4)  # 图像截取的横向起始位置
        end_x = int(width * 0.7)  # 图像截取的横向结束位置
        start_y = int(height * 0.6)  # 图像截取的纵向起始位置
        end_y = int(height * 0.9)  # 图像截取的纵向结束位置

        # 截取图像
        cropped_image = screen_image[start_y:end_y, start_x:end_x]

        results = {
            "red": {"locs": [], "key": "1"},
            "yellow": {"locs": [], "key": "2"},
            "blue": {"locs": [], "key": "3"},
        }
        # cv2.imshow("cropped_image", cropped_image)
        # cv2.waitKey(0)

        # 使用截取后的图像进行红色图案检测
        result_red = cv2.matchTemplate(cropped_image, self.template_red, self.method)
        loc_red = np.where(result_red >= self.threshold)
        results["red"]["locs"].extend(list(zip(*loc_red[::-1])))

        # 使用截取后的图像进行蓝色图案检测
        result_blue = cv2.matchTemplate(cropped_image, self.template_blue, self.method)
        loc_blue = np.where(result_blue >= self.threshold)
        results["blue"]["locs"].extend(list(zip(*loc_blue[::-1])))

        # 使用截取后的图像进行黄色图案检测
        result_yellow = cv2.matchTemplate(cropped_image, self.template_yellow, self.method)
        loc_yellow = np.where(result_yellow >= self.threshold)
        results["yellow"]["locs"].extend(list(zip(*loc_yellow[::-1])))

        for color, data in results.items():
            locs = data["locs"]
            for pt in locs:
                if not getattr(self, f"{color}_detected_in_image"):
                    setattr(self, f"{color}_detected_in_image", True)
                    if not self.first_detection_done:
                        self.first_detection_done = True
                        print(
                            f"{datetime.now().strftime('%H-%M-S-%f')[:-3]} 首次检测到{color}图案，延迟0.5秒后重新获取屏幕截图进行识别")
                        time.sleep(0.2)
                        return self.detect_patterns()
        return results

    def perform_key_presses(self, detection_results):
        """
        根据模板匹配得到的检测结果，执行相应的模拟按键操作，并打印相关信息。
        在同一次匹配过程中，确保每个图案对应的按键只按下一次。

        :param detection_results: 包含三个图案各自匹配到的图案位置信息以及对应按键值的字典，由detect_patterns方法返回
        """
        for color in ["red", "blue", "yellow"]:
            data = detection_results[color]
            locs = data["locs"]
            key = data["key"]
            if locs and not getattr(self, f"{color}_key_pressed"):
                print(f"{datetime.now().strftime('%H-%M-%S-%f')[:-3]} 识别到{color}图案，模拟按下键盘数字键{key}")
                # pyautogui.press(key)
                self.presser.press_by_str(key)
                setattr(self, f"{color}_key_pressed", True)
            # 重置按键按下标记，为下一次匹配做准备
            setattr(self, f"{color}_key_pressed", False)

    def run_detection(self):
        """
        运行整个图案检测流程的方法，通过监听F8快捷键来切换运行状态，实现循环执行或暂停循环，执行时不断重复执行截取屏幕、识别、按键、打印操作，切换状态时播放提示音。
        """

        def on_press(key):
            if key.name == 'f8':
                self.is_running = not self.is_running
                print(f"程序状态切换为: {'执行循环' if self.is_running else '暂停循环'}")
                if self.is_running:
                    winsound.Beep(1000, 300)  # 频率为1000Hz，持续300毫秒的声音，表示开启
                else:
                    winsound.Beep(600, 300)  # 频率为600Hz，持续300毫秒的声音，表示关闭

        keyboard.on_press(on_press)

        while True:
            if self.is_running:
                detection_results = self.detect_patterns()
                self.perform_key_presses(detection_results)
            time.sleep(0.2)


if __name__ == "__main__":
    template_red = cv2.imread('red.png')
    template_blue = cv2.imread('blue.png')
    template_yellow = cv2.imread('yellow.png')

    detector = PatternDetector(template_red, template_blue, template_yellow)
    detector.run_detection()
